package dataMining.apriori3;

/**
 * @author cuih
 * Date: 13-5-21
 * @function
 */

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;

public class Find_frequent_n {
    Find_frequent_1 freq_1 = new Find_frequent_1();
    boolean[][] DATA = freq_1.DATA;   //全局数据表，用于数据的
    int max = 0;//用于记录候选频繁项集的个数
    ArrayList[] frequent_item_list = new ArrayList[1000000];     //存放频繁项集
    ArrayList[] candidateList = new ArrayList[1000000]; //存放候选项集
    int[] sup = new int[1000000];//为每个项集定义一个支持度
    int count = 0;              //计算频繁项集的总个数

    void find_frequent(ArrayList[] L, int K) throws IOException {   //L表示前一个频繁项集
        //生成候选项集,连接操作
        for (int i = 0; ; i++) {
            if (L[i] == null) {          //为空跳出循环的便利
                break;
            }
            for (int j = i + 1; ; j++) {
                if (L[j] == null) {
                    break;
                }
                boolean flag = true;                  //候选标志位，成功则表示成true，默认表示能够进行连接操作
                int position = 0;                     //比较是否相同的位置

                //是否相同进行遍历
                while (position < (K - 2)) {                //定位前一个位置。K位置是在频度下的支持度计数,倘若需要的K=3,只需要比较第一个就行也就是0位置
                    if (Integer.parseInt(L[i].get(position).toString())
                            != Integer.parseInt(L[j].get(position).toString())) {      //对比两个位置的值，该处进行数值之间的转化
                        flag = false;
                    }
                    position++;
                }

                //生成候选项集
                if (flag) {
                    candidateList[max] = new ArrayList(K);    //生成一个K项集
                    for (int m = 0; m < (K - 1); m++) {
                        candidateList[max].add(L[i].get(m));   //L[i]全部赋值给候选项集
                    }
                    candidateList[max].add(L[j].get(K - 2));     //将L【j】中的元素添加入候选项集
                    scanDB(candidateList[max], K);                 //对候选项集进行筛选，直接排出非频繁项集
                    max++;                                       //候选计数器增加
                } //生成结束
            }
        }

        //对频繁2项集的文件进行输出
        File outDataFile = new File(AprioriFrequentItemset.outputFile);// 定义输出文件
        FileWriter ps = new FileWriter(outDataFile, true);
        ps.write("频繁" + K + "项集包括：\r\n");
        for (int i = 0; i <= max; i++) {
            if (sup[i] >= AprioriFrequentItemset.sup_absolute) { //支持度大于所需要的支持度
                frequent_item_list[count] = new ArrayList(K);      //存放频繁项集的arrayList，并且进行初始化
                for (int j = 0; j < K; j++) {
                    Object item = candidateList[i].get(j);
                    ps.write(item + " ");  //将该数进行输出
                    frequent_item_list[count].add(item);
                }
                ps.write(":" + sup[i] + "\r\n");    //写入数据
                frequent_item_list[count].add(sup[i]);      //最后一位写入频繁度
                count++;                               //总的记录频繁项集的数目
            }
        }
        ps.write("频繁" + K + "项集总计" + count + "个\r\n");
        ps.close();
        if (AprioriFrequentItemset.K > K) {                        //总的整数K是否大于该层的K，大于则继续向下一层调用
            Find_frequent_n find_frequent_n = new Find_frequent_n();
            find_frequent_n.find_frequent(frequent_item_list, K + 1);    //
        }
    }

    //扫描数据库，对两个项集分别进行检验计数，得到其最终的支持度
    void scanDB(ArrayList C, int K) {
        boolean flag = true;                             //定义一个临时标志，用于判定该数在数据库中是否存在
        sup[max] = 0;                                   //支持度初始化为0
        int[] temp = new int[K];                          //声明一个临时的数组存放item

        //首先将数据直接全部取出，得到性能全局的优化
        for (int j = 0; j < K; j++) {                            //K个数据一次便利
            temp[j] = Integer.parseInt(C.get(j).toString());  //将数据强制转换为int类型  ，并且存在temp里面
        }

        for (int i = 0; i < 8024; i++) {
            int j = 0;
            while (j < K) {
                if (!DATA[i][temp[j]]) {       //只要有不存在的则支持度不能增加
                    flag = false;                //标志位改变，跳出
                    break;
                }
                j++;
            }
            if (flag) {                                         //全部都存在，则频繁度增加
                sup[max]++;
            }
            flag = true;                                   //恢复标志位
        }

    }
}
//处理结果 ，将该数据形成候选项集，并且将候选项集传入，进行单个扫面，出结果可继续操作
